/*
 * Copyright (c) 2007 Compl Yue Still, All Rights Reserved.
 */

package hbi.as3.utils
{
	import flash.utils.*;
	
	public class ArrayType
	{
		
		public static function arrayTypeOf(obj:*):ArrayType
		{
			var array:Array = obj as Array;
			if(!array) return null;
			
			var dim:uint = 1;
			var eType:Class = null;
			while(true)
			{
				var element:*;
				for each (var e:* in array)
				{
					if(!e) continue;
					if(eType == null) // got first element carrying type
					{
						eType = e is int ? int : e.constructor;
						element = e;
					}
					else if (!(e is eType)) // inconsistent element type
					{
						return null;
					}
				}
				if(eType == null) // no element carries type
					return null;
				
				if(eType != Array) // gotcha
				{
					if(dim > 1) // need validation
						if(!validateElementType(obj, eType, dim))
							return null;
					return new ArrayType(eType, dim);
				}
				
				dim++;
				eType = null;
				array = element;
			}
			return null; // unreachable code actually
		}
		
		private static function validateElementType
			(array:Array, eType:Class, dim:uint):Boolean
		{
			var ele:*;
			
			if(dim <= 1)
			{
				for each (ele in array)
					if(!(ele is eType)) return false;
			}
			else
			{
				dim--;
				for each (ele in array)
				{
					if(!(ele is Array)) return false;
					if(!validateElementType(ele, eType, dim)) return false;
				}
			}

			return true;
		}
		
		private var _elementType:Class;
		private var _dimension:uint;
		
		public function ArrayType(elementType:Class, dimension:uint)
		{
			this._elementType = elementType;
			this._dimension = dimension;
		}
		
		public function get elementType():Class
		{
			return this._elementType;
		}
		
		public function get dimension():uint
		{
			return this._dimension;
		}
		
		public function toString():String
		{
			var s:String = "";
			for(var dim:uint=dimension; dim>0; dim--)
				s += '[';
			s += getQualifiedClassName(_elementType);
			return s;
		}
		
	}
}
